package org.xiaov.core.factory;

import lombok.extern.slf4j.Slf4j;
import org.xiaov.common.bean.AutoCodeInfo;
import org.xiaov.common.bean.PropertyInfo;
import org.xiaov.common.exception.AutoCodeBizException;
import org.xiaov.common.util.MySqlToJavaUtil;
import org.xiaov.core.service.AutoCodeBiz;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

/**
 * <p>
 * 描述：
 * </p>
 *
 * @author xiaovcloud
 * @since 2021/9/16 22:23
 */
@Slf4j
public class AutoCodeFactory {

    AutoCodeInfo autoCodeInfo;

    public AutoCodeFactory(AutoCodeInfo basisInfo) {
        checkConfig(basisInfo);
        this.autoCodeInfo = basisInfo;
    }

    private void checkConfig(AutoCodeInfo basisInfo) {
//        if (StringUtil.isNullOrEmpty(basisInfo.getDbUrl())) {
//            throw new AutoCodeBizException("数据库url未填");
//        }
//        if (StringUtil.isNullOrEmpty(basisInfo.getDbUsername())) {
//            throw new AutoCodeBizException("数据库用户名未填");
//        }
//        if (StringUtil.isNullOrEmpty(basisInfo.getDbPassword())) {
//            throw new AutoCodeBizException("数据库密码未填");
//        }
//        if (StringUtil.isNullOrEmpty(basisInfo.getFileHost())) {
//            throw new AutoCodeBizException("文件生成地址未填");
//        }
//        if (StringUtil.isNullOrEmpty(basisInfo.getPackPath())) {
//            throw new AutoCodeBizException("包路径未填写");
//        }
    }

    /**
     * 生成数据文件
     */
    public boolean generator() {
        DatabaseFactory databaseFactory = new DatabaseFactory(autoCodeInfo);
        for (String tableName : autoCodeInfo.getTables()) {
            StringBuilder sqlColumn = new StringBuilder();
            StringBuilder sqlTable = new StringBuilder();
            //获取主键
            sqlTable.append("SELECT column_name FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME = '")
                    .append(tableName)
                    .append("'");
            //获取字段名,数据类型,列描述
            sqlColumn.append("select column_name,data_type,column_comment from information_schema.columns where table_name = '")
                    .append(tableName)
                    .append("' order by ordinal_position");

            try {
                //查询出主键
                ResultSet resultSetTable = executeQuery(databaseFactory, sqlTable.toString(), tableName);
                String pk = "-1";
                while (resultSetTable.next()) {
                    pk = resultSetTable.getString(1);
                }

                ResultSet resultSetColumn = executeQuery(databaseFactory, sqlColumn.toString(), tableName);
                //列字段
                List<PropertyInfo> cis = new ArrayList<>();
                //引入的基本包
                Set<String> pkgs = new TreeSet<>();
                while (resultSetColumn.next()) {
                    String column = resultSetColumn.getString(1);
                    String jdbcType = resultSetColumn.getString(2);
                    String comment = resultSetColumn.getString(3);
                    PropertyInfo ci = new PropertyInfo();
                    ci.setColumn(column);
                    ci.setJdbcType(jdbcType);
                    ci.setComment(comment);
                    ci.setProperty(MySqlToJavaUtil.changeToJavaFiled(column, autoCodeInfo.getUnderLine2CamelCase()));
                    ci.setJavaType(MySqlToJavaUtil.jdbcTypeToJavaType(jdbcType));
                    //添加包路径
                    if (MySqlToJavaUtil.jdbcTypeToJavaTypePck(jdbcType) != null) {
                        pkgs.add(MySqlToJavaUtil.jdbcTypeToJavaTypePck(jdbcType));
                    }
                    cis.add(ci);
                }
                AutoCodeBiz.createFile(autoCodeInfo, tableName, cis, pkgs, pk);
            } catch (SQLException e) {
                e.printStackTrace();
                throw new AutoCodeBizException("自动生成实体类[{}]错误：", tableName, e);
            }
        }
        return true;
    }

    /**
     * 执行sql
     *
     * @param databaseFactory 连接工厂
     * @param sql             执行的sql
     * @return ResultSet
     */
    private ResultSet executeQuery(DatabaseFactory databaseFactory, String sql, String tableName) throws SQLException {
        Long start = System.currentTimeMillis();
        Connection connection = databaseFactory.getConnection();
        Long end = System.currentTimeMillis();

        if (connection == null) {
            throw new AutoCodeBizException("连接数据库未成功");
        }

        PreparedStatement preparedStatement = connection.prepareStatement(sql);
        log.info("获取数据库连接的时间:{}ms, 执行sql:{}", end - start, sql);
        ResultSet resultSet = preparedStatement.executeQuery();

        if (!resultSet.isBeforeFirst()) {
            throw new AutoCodeBizException("根据表[{}]未找到数据", tableName);
        }
        return resultSet;
    }
}
